#include "BayesianFilter.h"
#include "BayesianFilterSerializer.h"
#include "BayesianHelper.h"
#include "Configuration.h"
#include "Log.h"
#include "MainEngine.h"
#include "MainState.h"
#include "MainThread.h"
#include "Test_BayesianFilter.h"
#include "xmlrpc_support.h"
#include <errno.h>

#include "iostream.h"
#include "fstream.h"
#include <sys/stat.h>

#include <list>

using namespace std;

int FileExists ( const char* fileName )
{
	int retval = 0;
	
	ifstream tmp;
	tmp.open(fileName,ios::in);
	if ( tmp.is_open() ) retval = 1;
	tmp.close();

	return retval;
}


BayesianFilter* CreateBayesianFilter ()
{
	BayesianFilter* retval = new BayesianFilter ();

	LOG1("  Deserializing Bayesian Filter stop words...");
	if ( !BayesianHelper::Deserialize(BAYES_STOPWORDS_FILE) )
		LOG1("    Error deserializing... Stop words list will not be available.");
	else
	{
		LOG1("    Deserialization OK.");

		string stopWords = "";
		set<string>::iterator iterStop = BayesianHelper::stopWords.begin();
		for ( ; iterStop != BayesianHelper::stopWords.end() ; iterStop++ )
			stopWords += *iterStop + "; ";
	}
	
				
	LOG1("  Deserializing Bayesian Filter...");
	int bayesData   = FileExists(BAYES_DATA_FILE);
	int bayesMatrix = FileExists(BAYES_MATRIX_FILE);

	if ( bayesData )   
		LOG2("    Data file found:   ",BAYES_DATA_FILE);
	else
		LOG2("    Data file not found:   ",BAYES_DATA_FILE);
		
	if ( bayesMatrix ) 
		LOG2("    Matrix file found: ",BAYES_MATRIX_FILE);
	else
		LOG2("    Matrix file not found:   ",BAYES_MATRIX_FILE);
		
	if ( !bayesData || !bayesMatrix )
		LOG1("    Unable to deserialize. Starting from scratch.");
	else
	{
		LOG1("    Starting deserialization...");

		try
		{
			BayesianFilterSerializer serializer(*retval);
			serializer.Deserialize(BAYES_DATA_FILE,BAYES_MATRIX_FILE);		
		}
		catch ( char* ex )
		{
			LOG2("    Fatal Exception, starting from scratch: ",ex);
		}
	}
	
	return retval;
}


MainState* CreateMainState ()
{
	MainState* retval = new MainState ();

	LOG1("  Creating Main State...");
	
	LOG1("    Building giant lock...");
	retval->giantLock = new Lock();
	
	LOG1("    Initializing Feed Manager...");
	retval->feedManager = new FeedManager();	
	retval->feedManager->InicializarManager(FEEDS_DIR);

	LOG1("    Initializing News Manager...");
	retval->newsManager = new NewsManager();
	retval->newsManager->InicializarManager(NEWS_DIR);

	LOG1("    Initializing Tags Manager...");
	retval->tagsManager = new TagsManager();
	retval->tagsManager->InicializarManager(TAGS_DIR);

	LOG1("    Initializing Tag Map...");
	retval->mapaCategorias = new MapaCategorias();

	list<FeedItemConsulta>::iterator iter;
	list<FeedItemConsulta> feeds = retval->feedManager->ConsultarFeed();
	for ( iter = feeds.begin() ; iter != feeds.end() ; iter++ )
		LOG4("      ",(*iter).getPosicionGlobal()," ",(*iter).getURL());
	
	return retval;
}

int createdir(char *dname, char *prefix)
{
	struct stat st;
	int retval = 0;
	int size=strlen(dname)+strlen(prefix)+2;
	char *dirname = (char*)malloc(size);
	
	if(strlen(prefix)==0)
		snprintf(dirname,size,"%s",dname);
	
	else
	{
		if(stat(prefix,&st)!=0)
	        {
        	        free(dirname);
                	perror("stat() failed on target dir");
                	return 0;
        	}
        	if(!S_ISDIR(st.st_mode))
        	{
                	free(dirname);
                	printf("%2 not a directory\n",prefix);
                	return 0;
        	}
		snprintf(dirname,size,"%s/%s",prefix,dname);
	}
		
	if(stat(dirname,&st)!=0 && errno == ENOENT)
	{
		//the directory does not exist
		if(mkdir(dirname,0755)!=0)
		{
			free(dirname);
			perror("cannot create dir");
			return 0;
		}
		
	}

	free(dirname);
	return 1;
}


int initdirstruct()
{
	return createdir("tags",TAGS_DIR)&&createdir("news",NEWS_DIR)&&createdir("feeds",FEEDS_DIR);
}

int main(int argc, char** argv)
{
	if (initdirstruct())
	{
		LOG1("Initializing TP Datos 1er Cuatrimestre 2007 - Catedra Saubidet");
		LOG1("Version v0.0.1 - 12/06/07");
	
		BayesianFilter* bf = CreateBayesianFilter ();
		MainState* state   = CreateMainState ();
		state->bayesianFilter = bf;

		LOG1("  Creating Main Engine...");
		MainEngine* mainEngine = new MainEngine (state);

		LOG1("  Creating Main Thread...");
		MainThread mainThread(state);
		mainThread.start();
	
		LOG1("  XmlRpc Support Listening in port 32678...");
		LOG1("Ready.");
		FeedReaderXmlRpcSupport::Run ( mainEngine , 32678 );

		delete state->giantLock;
		delete state->feedManager;
		delete state;
		delete bf;
		return 0;
	}
	else
	{
		LOG1("Initialization of Directories FAILED!");
	}
}
